package org.summer.lawyer.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.summer.common.core.constant.Constants;
import org.summer.common.core.exception.ServiceException;
import org.summer.common.core.utils.MapstructUtils;
import org.summer.common.json.utils.JsonUtils;
import org.summer.common.mybatis.core.page.PageQuery;
import org.summer.common.mybatis.core.page.TableDataInfo;
import org.summer.lawyer.constant.SystemConstants;
import org.summer.lawyer.constant.enums.DispatchOrderStatus;
import org.summer.lawyer.constant.enums.OrderStatus;
import org.summer.lawyer.domain.SpuOrder;
import org.summer.lawyer.domain.bo.payorder.PayOrderBo;
import org.summer.lawyer.domain.bo.spuorder.*;
import org.summer.lawyer.domain.bo.spuorderassign.SpuOrderAssignBo;
import org.summer.lawyer.domain.bo.spuorderassign.TakeCompletedOrderBo;
import org.summer.lawyer.domain.bo.spuorderitem.SpuOrderItemBo;
import org.summer.lawyer.domain.vo.category.CategoryVo;
import org.summer.lawyer.domain.vo.lawfirm.LawFirmVo;
import org.summer.lawyer.domain.vo.spu.SpuVo;
import org.summer.lawyer.domain.vo.spuorder.*;
import org.summer.lawyer.domain.vo.spuorderassign.SpuAssignOrderStat;
import org.summer.lawyer.domain.vo.spuorderassign.SpuOrderAssignVo;
import org.summer.lawyer.domain.vo.spuorderitem.SpuOrderItemVo;
import org.summer.lawyer.domain.vo.wxuser.WxUserVo;
import org.summer.lawyer.event.SpuOrderAssignEvent;
import org.summer.lawyer.event.SpuOrderCompletedEvent;
import org.summer.lawyer.event.SpuOrderTimeoutEvent;
import org.summer.lawyer.mapper.SpuOrderMapper;
import org.summer.lawyer.service.*;
import org.summer.lawyer.util.IdWorkerUtil;
import org.summer.lawyer.util.ParamsUtil;

import java.util.*;

/**
 * 订单信息Service业务层处理
 *
 * @author summer
 * @date 2024-06-21
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SpuOrderServiceImpl extends ServiceImpl<SpuOrderMapper, SpuOrder> implements ISpuOrderService, ApplicationEventPublisherAware {

    private final ISpuService spuService;

    private final ISpuOrderItemService spuOrderItemService;

    private final ILawFirmService lawFirmService;

    private final ISpuOrderAssignService spuOrderAssignService;

    private final ICategoryService categoryService;

    private final IWxUserService wxUserService;

    //private final ISpuCommentService spuCommentService;


//    private final IPayOrderService payOrderService;
//
//    private final IPayChannelService payChannelService;
//
//    private final IPayAppService payAppService;

    /**
     * 查询订单信息
     *
     * @param orderId 主键
     * @return 订单信息
     */
    @Override
    public SpuOrderVo selectSpuOrderVoById(Long orderId) {
        SpuOrderVo spuOrderVo = baseMapper.selectUserOrderByOrderId(orderId);
        if (spuOrderVo != null) {
            //订单子项
            SpuOrderItemVo orderItemVo = spuOrderItemService.selectSpuOrderItemVoByOrderId(orderId);
            if (orderItemVo != null) {
                spuOrderVo.setOrderItemId(orderItemVo.getOrderItemId());
                spuOrderVo.setSpuId(orderItemVo.getSpuId());
                spuOrderVo.setSpuName(orderItemVo.getSpuName());
                spuOrderVo.setCategoryId(orderItemVo.getCategoryId());
                spuOrderVo.setCategoryName(orderItemVo.getCategoryName());
                spuOrderVo.setSpuImage(orderItemVo.getSpuImage());
                spuOrderVo.setSpuPrice(orderItemVo.getSpuPrice());
                spuOrderVo.setSpuTotalAmount(orderItemVo.getSpuTotalAmount());
                spuOrderVo.setSpuCount(orderItemVo.getSpuCount());
                spuOrderVo.setSpuFile(orderItemVo.getSpuFile());
            }
        }
        return spuOrderVo;
    }

    /**
     * 分页查询订单信息列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 订单信息分页列表
     */
    @Override
    public TableDataInfo<SpuOrderVo> selectPageList(SpuOrderBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SpuOrder> lqw = buildQueryWrapper(bo);
        Page<SpuOrderVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<SpuOrderVo> selectUserOrderPageList(SpuOrderBo bo, PageQuery pageQuery) {
        QueryWrapper<SpuOrderBo> queryWrapper = buildUserOrderQueryWrapper(bo);
        queryWrapper.orderByDesc("so.order_time");
        Page<SpuOrderVo> result = baseMapper.selectUserOrderPageList(pageQuery.build(), queryWrapper);
        return TableDataInfo.build(result);
    }

    private QueryWrapper<SpuOrderBo> buildUserOrderQueryWrapper(SpuOrderBo bo) {
        Map<String, Object> params = ParamsUtil.getParams(bo.getParams());
        QueryWrapper<SpuOrderBo> queryWrapper = Wrappers.query();
        queryWrapper.eq("so.del_flag", Constants.DEL_FLAG_NOT_DEL);
        queryWrapper.eq(bo.getUserId() != null, "so.user_id", bo.getUserId());
        queryWrapper.eq(StrUtil.isNotBlank(bo.getPayed()), "so.payed", bo.getPayed());
        queryWrapper.eq(StrUtil.isNotBlank(bo.getOrderStatus()), "so.order_status", bo.getOrderStatus());
        queryWrapper.eq(StrUtil.isNotBlank(bo.getReview()), "so.review", bo.getReview());
        queryWrapper.between(params.get("beginTime") != null && params.get("endTime") != null, "so.order_time", params.get("beginTime"), params.get("endTime"));
        return queryWrapper;
    }

    /**
     * 查询符合条件的订单信息列表
     *
     * @param bo 查询条件
     * @return 订单信息列表
     */
    @Override
    public List<SpuOrderVo> selectSpuOrderVoList(SpuOrderBo bo) {
        LambdaQueryWrapper<SpuOrder> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<SpuOrder> buildQueryWrapper(SpuOrderBo bo) {
        Map<String, Object> params = ParamsUtil.getParams(bo.getParams());
        LambdaQueryWrapper<SpuOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(SpuOrder::getPayed, "1");
        lqw.eq(StrUtil.isNotBlank(bo.getOrderNumber()), SpuOrder::getOrderNumber, bo.getOrderNumber());
        lqw.eq(StrUtil.isNotBlank(bo.getOrderStatus()), SpuOrder::getOrderStatus, bo.getOrderStatus());
        lqw.eq(StrUtil.isNotBlank(bo.getServiceType()), SpuOrder::getServiceType, bo.getServiceType());
        lqw.eq(StrUtil.isNotBlank(bo.getContactPhone()), SpuOrder::getContactPhone, bo.getContactPhone());
        lqw.eq(bo.getUserId() != null, SpuOrder::getUserId, bo.getUserId());
        lqw.like(StrUtil.isNotBlank(bo.getUserName()), SpuOrder::getUserName, bo.getUserName());
        lqw.eq(bo.getOrderTime() != null, SpuOrder::getOrderTime, bo.getOrderTime());
        lqw.eq(bo.getAmount() != null, SpuOrder::getAmount, bo.getAmount());
        lqw.eq(StrUtil.isNotBlank(bo.getPaymentMethod()), SpuOrder::getPaymentMethod, bo.getPaymentMethod());
        lqw.eq(bo.getPaymentAmount() != null, SpuOrder::getPaymentAmount, bo.getPaymentAmount());
        lqw.eq(bo.getPaymentTime() != null, SpuOrder::getPaymentTime, bo.getPaymentTime());
        lqw.eq(bo.getCompletionTime() != null, SpuOrder::getCompletionTime, bo.getCompletionTime());
        lqw.eq(StrUtil.isNotBlank(bo.getTransactionId()), SpuOrder::getTransactionId, bo.getTransactionId());
        lqw.eq(StrUtil.isNotBlank(bo.getReview()), SpuOrder::getReview, bo.getReview());
        lqw.eq(StrUtil.isNotBlank(bo.getOrderRemark()), SpuOrder::getOrderRemark, bo.getOrderRemark());
        lqw.eq(bo.getCancellationTime() != null, SpuOrder::getCancellationTime, bo.getCancellationTime());
        lqw.eq(StrUtil.isNotBlank(bo.getCloseType()), SpuOrder::getCloseType, bo.getCloseType());
        lqw.between(params.get("beginTime") != null && params.get("endTime") != null, SpuOrder::getOrderTime, params.get("beginTime"), params.get("endTime"));
        return lqw;
    }

    /**
     * 新增订单信息
     *
     * @param bo 订单信息
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(SpuOrderBo bo) {
        SpuOrder add = MapstructUtils.convert(bo, SpuOrder.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setOrderId(add.getOrderId());
        }
        return flag;
    }

    /**
     * 修改订单信息
     *
     * @param bo 订单信息
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(SpuOrderBo bo) {
        SpuOrder update = MapstructUtils.convert(bo, SpuOrder.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(SpuOrder entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除订单信息信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @DSTransactional(rollbackFor = Exception.class)
    @Override
    public SpuOrderVo create(SpuOrderCreateBo bo) {
        //创建订单
        SpuVo spuVo = spuService.selectSpuVoById(bo.getSpuId());
        WxUserVo wxUserVo = wxUserService.selectWxUserVoById(bo.getWxUserId());
        SpuOrder spuOrder = new SpuOrder();
        spuOrder.setOrderNumber(IdWorkerUtil.nextIdStr());
        spuOrder.setOrderStatus(OrderStatus.PENDING.getCode());
        spuOrder.setPayed("0");
        spuOrder.setOrderTime(DateUtil.date());
        spuOrder.setUserId(bo.getWxUserId());
        spuOrder.setUserName(bo.getContactName());
        if (StrUtil.isEmpty(bo.getContactName())) {
            spuOrder.setUserName(wxUserVo.getNickname());
        }
        spuOrder.setContactPhone(bo.getContactPhone());
        spuOrder.setAmount(spuVo.getPriceFee());
        spuOrder.setPaymentAmount(0L);
        spuOrder.setUserName(wxUserVo.getNickname());

        //spuOrder.setPaymentMethod(PaymentMethod.WECHAT_MINIAPP.getCode());
        //spuOrder.setServiceType(String.valueOf(spuVo.getCategoryId()));
        spuOrder.setServiceType(spuVo.getSpuName());
        spuOrder.setEmail(bo.getEmail());
        spuOrder.setReview("0");
        spuOrder.setOrderRemark(bo.getRemark());
        spuOrder.setDispatchable(spuVo.getDispatchable());
        baseMapper.insert(spuOrder);
        //创建订单子项
        SpuOrderItemBo spuOrderItemBo = new SpuOrderItemBo();
        spuOrderItemBo.setOrderId(spuOrder.getOrderId());
        spuOrderItemBo.setSpuId(spuVo.getSpuId());
        spuOrderItemBo.setSpuName(spuVo.getSpuName());
        spuOrderItemBo.setSpuPrice(spuVo.getPriceFee());
        spuOrderItemBo.setCategoryId(spuVo.getCategoryId());
        spuOrderItemBo.setCategoryName(spuVo.getCategoryName());
        spuOrderItemBo.setSpuImage(spuVo.getMainImgUrl());
        spuOrderItemBo.setSpuPrice(spuVo.getPriceFee());
        spuOrderItemBo.setSpuCount(bo.getCount());
        spuOrderItemBo.setUserId(spuOrder.getUserId());
        spuOrderItemBo.setUserName(spuOrder.getUserName());
        spuOrderItemBo.setSpuTotalAmount(spuOrderItemBo.getSpuPrice() * spuOrderItemBo.getSpuCount());
        spuOrderItemBo.setSpuFile(spuVo.getSubtitle());
        spuOrderItemService.insertByBo(spuOrderItemBo);
        //创建分派订单
        SpuOrderAssignBo sbo = new SpuOrderAssignBo();
        sbo.setOrderId(spuOrder.getOrderId());
        sbo.setSpuId(spuVo.getSpuId());
        sbo.setSpuName(spuVo.getSpuName());
        sbo.setCategoryId(spuVo.getCategoryId());
        sbo.setCategoryName(spuVo.getCategoryName());
        sbo.setSpuImage(spuVo.getMainImgUrl());
        sbo.setSpuPrice(spuVo.getPriceFee());
        sbo.setSpuCount(bo.getCount());
        sbo.setSpuTotalAmount(spuOrder.getAmount());
        sbo.setSpuFile(spuVo.getAttachmentId());
        spuOrderAssignService.insertByBo(sbo);
        //构造返回信息
        return baseMapper.selectVoById(spuOrder.getOrderId());
    }

    @Override
    public void spuOrderNotify(SpuOrderBo bo) {
        SpuOrderVo spuOrderVo = selectSpuOrderVoById(bo.getOrderId());
        if (spuOrderVo != null) {
            SpuOrder spuOrder = new SpuOrder();
            spuOrder.setOrderStatus(OrderStatus.PAID.getCode());
            spuOrder.setPaymentTime(bo.getPaymentTime());
            spuOrder.setPaymentMethod(bo.getPaymentMethod());
            spuOrder.setPaymentAmount(bo.getPaymentAmount());
            spuOrder.setTransactionId(bo.getTransactionId());
            spuOrder.setPayed("1");
            LambdaUpdateWrapper<SpuOrder> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.eq(SpuOrder::getOrderId, bo.getOrderId());
            baseMapper.update(spuOrder, updateWrapper);
        }
    }

    @Override
    public void refundSpuOrder(SpuOrderBo bo) {
        SpuOrderVo spuOrderVo = selectSpuOrderVoById(bo.getOrderId());
        if (spuOrderVo != null && OrderStatus.REFUNDED.getCode().equals(spuOrderVo.getOrderStatus())) {
            SpuOrder spuOrder = new SpuOrder();
            spuOrder.setOrderStatus(OrderStatus.REFUNDED.getCode());
            LambdaUpdateWrapper<SpuOrder> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.eq(SpuOrder::getOrderId, bo.getOrderId());
            baseMapper.update(spuOrder, updateWrapper);
        }
    }

    @Override
    public SpuAssignOrderStat selectSpuAssignOrderStatByWxUserId(Long wxUserId) {
        LawFirmVo lawFirmVo = lawFirmService.selectLawFirmVoByAdminId(wxUserId);
        return selectSpuAssignOrderStat(lawFirmVo.getLawFirmId());
    }

    @Override
    public SpuAssignOrderStat selectSpuAssignOrderStat(Long lawFirmId) {
        SpuAssignOrderStat orderStat = new SpuAssignOrderStat();
        Long orderCount = spuOrderAssignService.orderCountByLawFirmId(lawFirmId);
        Long completedOrderCount = spuOrderAssignService.completedOrderCountByLawFirmId(lawFirmId);
        Long confirmedOrderCount = spuOrderAssignService.confirmedOrderCountByLawFirmId(lawFirmId);
        Long returnedOrderCount = spuOrderAssignService.returnedOrderCountByLawFirmId(lawFirmId);
        Long reviewOrderCount = spuOrderAssignService.reviewOrderCountByLawFirmId(lawFirmId);
        orderStat.setOrderCount(orderCount);
        orderStat.setCompletedOrderCount(completedOrderCount);
        orderStat.setConfirmedOrderCount(confirmedOrderCount);
        orderStat.setOvertimeOrderCount(returnedOrderCount);
        orderStat.setReviewOrderCount(reviewOrderCount);
        return orderStat;
    }

    @Override
    public SpuOrderTotalStatVo selectSpuOrderTotalStatVo(SpuOrderStatBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<SpuOrderStatBo> queryWrapper = Wrappers.query();
        queryWrapper.eq("payed", "1");
        queryWrapper.eq("del_flag", Constants.DEL_FLAG_NOT_DEL);
        queryWrapper.between(params.get("beginTime") != null && params.get("endTime") != null, "order_time", params.get("beginTime"), params.get("endTime"));
        return baseMapper.selectSpuOrderStat(queryWrapper);
    }

    @Override
    public TableDataInfo<SpuOrderStatVo> selectSpuOrderStatVo(SpuOrderStatBo bo) {
        SpuOrderStatVo vo = new SpuOrderStatVo();
        //查询指定时间段统计
        SpuOrderTotalStatVo totalStatVo = selectSpuOrderTotalStatVo(bo);
        vo.setOrderCount(totalStatVo.getOrderCount());
        vo.setOrderAmount(totalStatVo.getOrderAmount());
        //查询七天统计
        Date now = DateUtil.date();
        Date before7Date = DateUtil.beginOfDay(DateUtil.offsetDay(now, -7));
        Date before30Date = DateUtil.beginOfDay(DateUtil.offsetDay(now, -30));
        Map<String, Object> params7Day = MapUtil.newConcurrentHashMap();
        params7Day.put("beginTime", before7Date);
        params7Day.put("endTime", now);
        bo.setParams(params7Day);
        SpuOrderTotalStatVo totalStatVo7Day = selectSpuOrderTotalStatVo(bo);
        vo.setWeekOrderCount(totalStatVo7Day.getOrderCount());
        vo.setWeekOrderAmount(totalStatVo7Day.getOrderAmount());
        //查询30天统计
        Map<String, Object> params30Day = MapUtil.newConcurrentHashMap();
        params7Day.put("beginTime", before30Date);
        params7Day.put("endTime", now);
        bo.setParams(params30Day);
        SpuOrderTotalStatVo totalStatVo30Day = selectSpuOrderTotalStatVo(bo);
        vo.setMonthOrderCount(totalStatVo30Day.getOrderCount());
        vo.setMonthOrderAmount(totalStatVo30Day.getOrderAmount());
        vo.setIndex(1);
        List<SpuOrderStatVo> list = CollUtil.newArrayList();
        list.add(vo);
        return TableDataInfo.build(list);
    }

    @Override
    public List<SpuOrderIncomeStatVo> selectSpuOrderIncomeStatVoList(SpuOrderIncomeStatBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<SpuOrderIncomeStatBo> lqw = Wrappers.query();
        lqw.eq("so.payed", "1");
        lqw.eq("so.del_flag", Constants.DEL_FLAG_NOT_DEL);
        lqw.and(bo.getCategoryId() != null, w -> {
            List<Long> categoryIds = getCategories(bo.getCategoryId());
            w.in("soi.category_id", categoryIds);
        });
        lqw.between(params.get("beginTime") != null && params.get("endTime") != null, "so.order_time", params.get("beginTime"), params.get("endTime"));
        lqw.groupBy("soi.category_name");
        List<SpuOrderIncomeStatVo> voList = baseMapper.selectSpuOrderIncomeStat(lqw);
        if (CollUtil.isNotEmpty(voList)) {
            int index = 1;
            for (SpuOrderIncomeStatVo spuOrderIncomeStatVo : voList) {
                spuOrderIncomeStatVo.setIndex(index);
                index++;
            }
        }
        return voList;
    }

    @Override
    public SpuOrderIncomeTotalStatVo selectSpuOrderIncomeTotalStatVo() {
        SpuOrderIncomeTotalStatVo vo = new SpuOrderIncomeTotalStatVo();
        vo.setIncomeAmount(0L);
        vo.setTodayIncomeAmount(0L);
        SpuOrderIncomeStatBo bo = new SpuOrderIncomeStatBo();
        //查询全部
        List<SpuOrderIncomeStatVo> incomeStatVos = selectSpuOrderIncomeStatVoList(bo);
        if(CollUtil.isNotEmpty(incomeStatVos)){
           Long incomeAmount = incomeStatVos.stream().mapToLong(SpuOrderIncomeStatVo::getOrderAmount).sum();
           vo.setIncomeAmount(incomeAmount);
        }
        //查询当天
        Date date = DateUtil.date();
        Map<String, Object> params = new HashMap<>();
        params.put("beginTime", DateUtil.beginOfDay(date));
        params.put("endTime", date);
        bo.setParams(params);
        List<SpuOrderIncomeStatVo> todayIncomeStatVos = selectSpuOrderIncomeStatVoList(bo);
        if(CollUtil.isNotEmpty(todayIncomeStatVos)){
            Long todayIncomeAmount = todayIncomeStatVos.stream().mapToLong(SpuOrderIncomeStatVo::getOrderAmount).sum();
            vo.setTodayIncomeAmount(todayIncomeAmount);
        }
        return vo;
    }

    @Override
    public void assigningSpuOrder(SpuOrderBo bo) {
        SpuOrderAssignVo vo = spuOrderAssignService.selectSpuOrderAssignVoBySpuOrderId(bo.getOrderId());
//        if (DispatchOrderStatus.PROCESSING.getCode().equals(vo.getDispatchStatus())) {
//            throw new ServiceException("该订单正在处理中，请勿重复派单");
//        }
        SpuOrderVo spuOrderVo = selectSpuOrderVoById(bo.getOrderId());
        SpuOrderAssignBo assignBo = new SpuOrderAssignBo();
        assignBo.setLawFirmId(bo.getLawFirmId());
        assignBo.setTrackingNumber(vo.getTrackingNumber());
        spuOrderAssignService.assigningOrder(assignBo);
        //更新当前订单状态
        SpuOrder spuOrder = new SpuOrder();
        spuOrder.setOrderStatus(OrderStatus.PROCESSING.getCode());
        spuOrder.setOrderId(bo.getOrderId());
        LambdaUpdateWrapper<SpuOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(SpuOrder::getOrderId, bo.getOrderId());
        baseMapper.update(spuOrder, updateWrapper);
        //分派订单
        vo = spuOrderAssignService.selectSpuOrderAssignVoBySpuOrderId(bo.getOrderId());
        applicationEventPublisher.publishEvent(new SpuOrderAssignEvent(this, vo));
    }

    @Override
    public void cancelSpuOrder(Long orderId) {
        SpuOrderVo spuOrderVo = selectSpuOrderVoById(orderId);
        SpuOrder spuOrder = new SpuOrder();
        spuOrder.setOrderId(orderId);
        spuOrder.setCancellationTime(DateUtil.date());
        spuOrder.setOrderStatus(OrderStatus.CANCELLED.getCode());
        spuOrder.setCloseType("1");
        LambdaUpdateWrapper<SpuOrder> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(SpuOrder::getOrderId, orderId);
        baseMapper.update(spuOrder, updateWrapper);
    }

    @Override
    public void revokeSpuOrder(SpuOrderBo bo) {
        SpuOrderAssignVo orderAssignVo = spuOrderAssignService.selectSpuOrderAssignVoByTrackingNumber(bo.getTrackingNumber());
        SpuOrderAssignBo assignBo = new SpuOrderAssignBo();
        assignBo.setId(orderAssignVo.getId());
        assignBo.setTrackingNumber(bo.getTrackingNumber());
        spuOrderAssignService.revokeSpuOrder(assignBo);
        applicationEventPublisher.publishEvent(new SpuOrderTimeoutEvent(this,orderAssignVo));
    }

    @Override
    public void testOrder(SpuOrderTestBo bo) {
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageSize(100);
        TableDataInfo<WxUserVo> userVoTableDataInfo = wxUserService.selectPageList(new WxUserVo(), pageQuery);
        List<WxUserVo> list = userVoTableDataInfo.getRows();
        int index = RandomUtil.randomInt(0, list.size() - 1);
        WxUserVo wxUserVo = list.get(index);
        SpuVo spuVo = spuService.selectSpuVoById(bo.getSpuId());
        //创建订单
        SpuOrderCreateBo orderCreateBo = new SpuOrderCreateBo();
        orderCreateBo.setSpuId(spuVo.getSpuId());
        orderCreateBo.setWxUserId(wxUserVo.getWxUserId());
        orderCreateBo.setContactName(wxUserVo.getNickname());
        orderCreateBo.setContactPhone(wxUserVo.getPhoneNumber());
        orderCreateBo.setEmail("whopietile@126.com");
        orderCreateBo.setCount(1);
        SpuOrderVo spuOrder = this.create(orderCreateBo);
        IPayOrderService payOrderService = SpringUtil.getBean(IPayOrderService.class);
        PayOrderBo payOrderBo = new PayOrderBo();
        payOrderBo.setOrderId(spuOrder.getOrderId());
        payOrderBo.setUserId(wxUserVo.getWxUserId());
        payOrderBo.setOpenId(wxUserVo.getOpenId());
        payOrderService.createTestPayOrder(payOrderBo);
    }


    @Override
    public void processedOrder(TakeCompletedOrderBo bo) {
        SpuOrderAssignVo vo = spuOrderAssignService.selectSpuOrderAssignVoByTrackingNumber(bo.getTrackingNumber());
        // SpuOrderAssignVo vo = spuOrderAssignService.selectSpuOrderAssignVoBySpuOrderId(Long.parseLong(bo.getTrackingNumber()));
        if (ObjectUtil.isNull(vo)) {
            log.error("[律师端申请完成][分派订单号：{}]， 未找到订单信息", bo.getTrackingNumber());
            throw new ServiceException("未找到订单信息");
        }
        if (SystemConstants.INACTIVE.equals(vo.getActive())) {
            throw new ServiceException("当前订单已经关闭");
        }
        //SpuOrderVo spuOrderVo = selectSpuOrderVoById(vo.getOrderId());
        if (DispatchOrderStatus.COMPLETED.getCode().equals(vo.getDispatchStatus())) {
            throw new ServiceException("已经提交过申请完成了");
        }
        if (DispatchOrderStatus.CONFIRMED.getCode().equals(vo.getDispatchStatus())) {
            SpuOrder spuOrder = new SpuOrder();
            spuOrder.setProcessedStatus("1");
            spuOrder.setProcessedTime(DateUtil.date());
            spuOrder.setOrderId(vo.getOrderId());
            LambdaUpdateWrapper<SpuOrder> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.eq(SpuOrder::getOrderId, vo.getOrderId());
            baseMapper.update(spuOrder, updateWrapper);
            SpuOrderAssignBo orderAssignBo = new SpuOrderAssignBo();
            orderAssignBo.setId(vo.getId());
            spuOrderAssignService.processedOrder(orderAssignBo);
        } else {
            log.error("[律师端申请完成][分派订单号：{}]，订单状态异常，参数：{}", bo.getTrackingNumber(), JsonUtils.toJsonString(vo));
            throw new ServiceException("订单状态异常,请刷新后再试");
        }
    }

    //@Lock4j(keys = "{#bo.orderId}", acquireTimeout = 1000, expire = 10000)
    @DSTransactional(rollbackFor = Exception.class)
    @Override
    public void completedOrder(CompletedOrderBo bo) {
        SpuOrderVo spuOrderVo = selectSpuOrderVoById(bo.getOrderId());
        if (OrderStatus.COMPLETED.getCode().equals(spuOrderVo.getOrderStatus())) {
            throw new ServiceException("订单已经完成，请勿重复提交");
        }
        SpuOrder spuOrder = new SpuOrder();
        spuOrder.setOrderStatus(OrderStatus.COMPLETED.getCode());
        spuOrder.setCompletionTime(DateUtil.date());
        LambdaUpdateWrapper<SpuOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(SpuOrder::getOrderId, bo.getOrderId());
        baseMapper.update(spuOrder, updateWrapper);
        //处理派单完成
        SpuOrderAssignVo orderAssignVo = spuOrderAssignService.selectSpuOrderAssignVoBySpuOrderId(bo.getOrderId());
        if (orderAssignVo != null) {
            SpuOrderAssignBo orderAssignBo = new SpuOrderAssignBo();
            orderAssignBo.setId(orderAssignVo.getId());
            orderAssignBo.setDispatchStatus(DispatchOrderStatus.FINISHED.getCode());
            orderAssignBo.setFinishedTime(spuOrder.getCompletionTime());
            spuOrderAssignService.completedAssigningOrder(orderAssignBo);
            // } else {
            //还没有派单就完成
        }
        spuOrderVo = selectSpuOrderVoById(bo.getOrderId());
        applicationEventPublisher.publishEvent(new SpuOrderCompletedEvent(this, orderAssignVo));

    }

    @Override
    public void completedReview(SpuOrderBo bo) {
        SpuOrderVo spuOrderVo = selectSpuOrderVoById(bo.getOrderId());
        SpuOrder spuOrder = new SpuOrder();
        spuOrder.setOrderId(bo.getOrderId());
        spuOrder.setReview("1");
        LambdaUpdateWrapper<SpuOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(SpuOrder::getOrderId, spuOrder.getOrderId());
        baseMapper.update(spuOrder, updateWrapper);
    }

    private ApplicationEventPublisher applicationEventPublisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    @Override
    public List<SpuOrderVo> selectTimeoutOrder(SpuOrderBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<SpuOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(SpuOrder::getOrderStatus, OrderStatus.PENDING.getCode());
        lqw.eq(SpuOrder::getPayed, "0");
        lqw.le(SpuOrder::getOrderTime, params.get("now"));
        return baseMapper.selectVoList(lqw);
    }

    private List<Long> getCategories(Long parentId) {
        List<CategoryVo> categoryVos = categoryService.selectCategoryVoListByParentId(parentId);
        List<Long> categoryIds = CollUtil.newArrayList();
        for (CategoryVo categoryVo : categoryVos) {
            categoryIds.add(categoryVo.getCategoryId());
        }
        return categoryIds;
    }


}
